package com.java.memory;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

//FAQ：假如现在内存比较小，不断向内存放入数据会出现什么现象？
//1)可能会触发GC
//2)内存溢出
//FAQ：程序启动前，如何设置JVM堆内存大小？
//1) -Xmx6m 最大堆大小
//2) -Xms6m 最小堆(初始堆大小)
//FAQ：程序运行时如何看到触发了GC操作？
//1)-XX:+PrintGC (打印GC基本信息)
//2)-XX:+PrintDetailGC (打印GC的详细信息)
public class MemoryTests {
    static void doCache01()throws InterruptedException{
        //定义一个Cache对象(底层存储结构为散列表)
        Map<Integer,Object> cache=new ConcurrentHashMap<>();
        //构建一个定时任务对象，每隔2秒清空一下缓存。
        Timer timer=new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("Clear Cache :"+System.currentTimeMillis());
                cache.clear();
            }
        }, 0, 2000);
        //向缓存放数据(map容器保存的是对象的一个强引用)
        for(int i=0;i<100;i++){
            cache.put(i, new byte[1024*1024]);
            TimeUnit.SECONDS.sleep(1);
        }
    }
    //通过软引用引用缓存中放入的对象，便于在内存不足触发GC时，清除缓存数据
    static void doCache02()throws InterruptedException{
        //定义一个Cache对象(底层存储结构为散列表)
        //SoftReference为Java中的一个软引用(软引用引用的对象在内存不足时触发GC操作，可以被移除)
        //SoftReference经常会应用在缓存中，作为缓存对象的引用。
        Map<Integer, SoftReference<byte[]>> cache=new ConcurrentHashMap<>();
        //向缓存放数据
        for(int i=0;i<100;i++){
            cache.put(i, new SoftReference<>(new byte[1024*1024]));
            TimeUnit.SECONDS.sleep(1);
        }
    }
    //通过弱引用(WeakReference)引用缓存中放入的对象，可以在触发GC时，清除缓存数据
    static void doCache03()throws InterruptedException{
        //定义一个Cache对象(底层存储结构为散列表)
        //WeakReference为Java中的一个弱引用(生命力比SoftReference还要弱一些)
        //WeakReference经常会应用在缓存中，作为缓存对象的引用。
        Map<Integer, WeakReference<byte[]>> cache=new ConcurrentHashMap<>();
        //向缓存放数据
        for(int i=0;i<100;i++){
            cache.put(i, new WeakReference<>(new byte[1024*1024]));
            TimeUnit.SECONDS.sleep(1);
        }
    }
    public static void main(String[] args) throws InterruptedException {
          //doCache01();
          //doCache02();
            doCache03();
    }
}
